home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 1833 / 1833.xpi / modules / yoonoYEXTIF.js < prev   
Text File  |  2009-12-16  |  39KB  |  1,067 lines

  1. var EXPORTED_SYMBOLS = ["YOONO_YEXTIF"];
  2.  
  3. Components.utils.import("resource://yoono/yoonoKeyValueDB.js");
  4. Components.utils.import("resource://yoono/yoonoPrefs.js");
  5.  
  6. // Globals
  7. const CI = Components.interfaces;
  8. const CL = Components.classes;
  9.  
  10. /////
  11. const YOONO_DIRSERVICE = Components.classes['@mozilla.org/file/directory_service;1'].getService(Components.interfaces.nsIProperties);
  12. const YOONO_SOUND = Components.classes["@mozilla.org/sound;1"].createInstance(Components.interfaces.nsISound);
  13. const COOKIE_MAN = CL["@mozilla.org/cookiemanager;1"].getService(CI.nsICookieManager).QueryInterface(CI.nsICookieManager2);
  14. const COOKIE_PERM = Components.classes['@mozilla.org/cookie/permission;1'].getService(Components.interfaces.nsICookiePermission);
  15. const WMED = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator);
  16.  
  17. const YNPREFSSERVICE = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
  18. const YNPREFS = YNPREFSSERVICE.getBranch("extensions.yoono.");
  19.  
  20. const YOONO_ID = "{d9284e50-81fc-11da-a72b-0800200c9a66}";
  21. /////
  22.  
  23. var yoono = {};
  24.  
  25. function YoonoExternalInterfaces() {
  26.   this.wrappedJSObject=this;
  27.   
  28.   this.methods = {};
  29.   this.singletonPopup = null;
  30.   this.popouted = {}; // store popouted yoodgets
  31.   this.yoodgetInstances = {}; // store all yoodget instances
  32.   
  33. }
  34.  
  35. YoonoExternalInterfaces.prototype.init = function (y) {
  36.   
  37.   yoono = y;
  38.   
  39.   // Wait for yoono var before setting methods
  40.   this.setMethods();
  41.   
  42.   this.initCookies();
  43.   
  44. }
  45.  
  46. YoonoExternalInterfaces.prototype.initCookies = function () {
  47. try {
  48.   
  49.   if (!this.methods.isStandalone()) {
  50.     var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
  51.                           .getService(Components.interfaces.nsIXULAppInfo);
  52.     var versionChecker = Components.classes["@mozilla.org/xpcom/version-comparator;1"]
  53.                                    .getService(Components.interfaces.nsIVersionComparator);
  54.     if(versionChecker.compare(appInfo.version, "3.5") < 0) {
  55.       // Disable cookies hacking on firefox 3.0
  56.       return;
  57.     }
  58.   }
  59.   
  60.   Components.utils.import("resource://yoono/yoonoCookies.js");
  61.   
  62.   var listener;
  63.   if (this.methods.isStandalone())
  64.     listener = this.getStandaloneCookiesListener();
  65.   else
  66.     listener = this.getFirefoxCookiesListener();
  67.   
  68.   CookiesService.init(listener);
  69.   
  70.   if (!this.methods.isStandalone()) {
  71.     CookiesService.FirefoxWindowsWatcher.start();
  72.   }
  73. } catch(e) {
  74.   yoono.log.exception(e);
  75. }
  76. }
  77.  
  78. YoonoExternalInterfaces.prototype.getStandaloneCookiesListener = function () {
  79.   var _self = this;
  80.   return {
  81.     getBrowserSessionId : function (browser) {
  82.       // No session restore for yoono desktop
  83.       return null;
  84.     },
  85.     onBrowserAttached : function (browser, session_id) {
  86.       
  87.       _self.getTopWindow().ynWebPanel._domWin.gAccountSelector.onTabSelect();
  88.       
  89.     },
  90.     onBrowserDetached : function (browser) {
  91.       
  92.     }
  93.   };
  94. }
  95.  
  96. YoonoExternalInterfaces.prototype.getFirefoxCookiesListener = function () {
  97.   var sessionStore = Components.classes["@mozilla.org/browser/sessionstore;1"].getService(Components.interfaces.nsISessionStore);
  98.   var _self = this;
  99.   return {
  100.     getBrowserSessionId : function (browser) {
  101.       try {
  102.         var gBrowser = browser.getTabBrowser();
  103.         var i = gBrowser.getBrowserIndexForDocument(browser.contentDocument);
  104.         var tab = gBrowser.tabContainer.childNodes[i];
  105.         
  106.         return sessionStore.getTabValue(tab, "cookies-db-id");
  107.       } catch(e) {
  108.         Components.utils.reportError(e);
  109.       }
  110.     },
  111.     onBrowserAttached : function (browser, session_id) {
  112.       // On Firefox, save an hint in session store 
  113.       // in order to be able to restore our cookies db
  114.       try {
  115.         var gBrowser = browser.getTabBrowser();
  116.         var i = gBrowser.getBrowserIndexForDocument(browser.contentDocument);
  117.         var tab = gBrowser.tabContainer.childNodes[i];
  118.         sessionStore.setTabValue(tab, "cookies-db-id", session_id);
  119.       } catch(e) {}
  120.       
  121.       // Then overload some tab methods to intercept location change
  122.       if (!browser._originalLoadURIWithFlags) {
  123.         browser._originalLoadURIWithFlags = browser.loadURIWithFlags;
  124.         browser.loadURIWithFlags = function (aURI, aFlags, aReferrerURI, aCharset, aPostData) {
  125.           //Components.utils.reportError("loadURI : "+browser);
  126.           var original = browser._originalLoadURIWithFlags;
  127.           browser._originalLoadURIWithFlags = null;
  128.           browser.loadURIWithFlags = original;
  129.           // When user go to another website, revert to default cookies database
  130.           //browser.parentNode.removeChild(browser.previousSibling);
  131.           CookiesService.detachSessionFromBrowser(browser);
  132.           
  133.           return original.call(browser, aURI, aFlags, aReferrerURI, aCharset, aPostData);
  134.         }
  135.       }
  136.       
  137.       //TODO: check this hack
  138.       //_self.getTopWindow().inspectObject([browser,browser.__parent__]);
  139.       browser.ownerDocument.defaultView.gAccountSelector.onTabSelect();
  140.     }, // end of onBrowserAttached
  141.     onBrowserDetached : function (browser) {
  142.       try {
  143.         var gBrowser = browser.getTabBrowser();
  144.         var i = gBrowser.getBrowserIndexForDocument(browser.contentDocument);
  145.         var tab = gBrowser.tabContainer.childNodes[i];
  146.         sessionStore.deleteTabValue(tab, "cookies-db-id");
  147.       } catch(e) {}
  148.       //TODO: check this hack
  149.       browser.ownerDocument.defaultView.gAccountSelector.onTabSelect();
  150.     }
  151.   };
  152. }// end of getFirefoxCookiesListener
  153.  
  154. YoonoExternalInterfaces.prototype.getYoonoGlob = function () {  
  155.   return this.getTopWindow().yoonoGlob;
  156. }
  157.   
  158. YoonoExternalInterfaces.prototype.getSidebar = function () {
  159.   return this.getYoonoGlob().sidebar;
  160. }
  161.  
  162. YoonoExternalInterfaces.prototype.setMethods = function () {
  163.   var _self = this;
  164.   
  165.   this.methods = {};
  166.  
  167.   this.methods.tosCallBack = function(action) {
  168.     var yoonoGlob = _self.getYoonoGlob();
  169.     yoonoGlob.tosPop = null;
  170.     switch(action) {
  171.       case 'accept':
  172.         yoonoGlob.tosAccepted = true;
  173.         yoono.prefs.set("tos-accepted", true);
  174.         yoonoGlob.sidebar.show();
  175.         yoono.main.getYServices().observer.notifyObservers("app.tos-accepted",null);
  176.         // add stat counter
  177.         var counter = 0;
  178.         function sendTosStat(){
  179.           if(yoonoGlob.sidebar && yoonoGlob.sidebar.win && yoonoGlob.sidebar.win.ynSidebar){
  180.             yoonoGlob.sidebar.win.ynSidebar.sendTOSAcceptedStat();
  181.           }
  182.           else if(counter < 5){
  183.             counter ++;
  184.             var timer = CL['@mozilla.org/timer;1'].createInstance(CI.nsITimer);
  185.             timer.initWithCallback(sendTosStat, 5000, timer.TYPE_ONE_SHOT);
  186.           }
  187.         }
  188.         sendTosStat();
  189.       break;                 
  190.       case 'uninstall':
  191.         yoono.main.addStat(['clic.wizard.uninstall']);
  192.         var extensionWindow = WMED.getMostRecentWindow("Extension:Manager");
  193.         var gExtensionManager = Components.classes["@mozilla.org/extensions/manager;1"].getService(Components.interfaces.nsIExtensionManager);
  194.         gExtensionManager.uninstallItem(YOONO_ID);
  195.       break;                 
  196.     }
  197.   } 
  198.   this.methods.log = function(m,caller) {yoono.log.debug(m,caller?caller:(Components.stack.caller?Components.stack.caller.caller:null))};
  199.   this.methods.logDebug = function(m,caller) {yoono.log.debug(m,caller?caller:(Components.stack.caller?Components.stack.caller.caller:null))};
  200.   this.methods.logWarning = function(m,caller) {yoono.log.warn(m,caller?caller:(Components.stack.caller?Components.stack.caller.caller:null))};
  201.   this.methods.logInfo = function(m,caller) {yoono.log.info(m,caller?caller:(Components.stack.caller?Components.stack.caller.caller:null))};
  202.   this.methods.logError = function(m,caller) {yoono.log.error(m,caller?caller:(Components.stack.caller?Components.stack.caller.caller:null))};
  203.   this.methods.logException = function(m,caller) {yoono.log.exception(m,caller?caller:(Components.stack.caller?Components.stack.caller.caller:null))};
  204.   this.methods.logFatal = function(m,caller) {yoono.log.fatal(m,caller?caller:(Components.stack.caller?Components.stack.caller.caller:null))};
  205.   this.methods.isErrorEnabled = function() {return yoono.log.isErrorEnabled();};
  206.   this.methods.isWarnEnabled = function() {return yoono.log.isWarnEnabled();};
  207.   this.methods.isInfoEnabled = function() {return yoono.log.isInfoEnabled();};
  208.   this.methods.isDebugEnabled = function() {return yoono.log.isDebugEnabled();};
  209.   this.methods.isStandalone = function() {
  210.     if (typeof _self._isStandaloneCache=="undefined") {
  211.       var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo);
  212.       _self._isStandaloneCache = appInfo.ID=="xulrunner@yoono.com";
  213.     }
  214.     return _self._isStandaloneCache;
  215.   };
  216.   this.methods.getClientType = function() {return 'xpi';};
  217.   
  218.   // Storage database initialization (creation, upgrading, opening)
  219.   this.methods.openStorage = function() {
  220.     yoono.storage.openStorage();
  221.   }
  222.   this.methods.backupDB = function(aVersion) {
  223.     yoono.storage.backupDB(aVersion);
  224.   }
  225.   this.methods.executeAsyncSql = function(aParams) {
  226.     var statement = aParams[0];// one sql query with placeholders
  227.     var values = aParams[1];   // double list with placeholder's values (optional)
  228.     var callback = aParams[2]; // callback function which will receive a double list of string (optional)
  229.     yoono.storage.executeAsyncSql(statement, values, callback);
  230.   }
  231.  
  232.   this.methods.getUserCredential = yoono.main.getUserCredential;
  233.  
  234.   this.methods.getVersion = function() {
  235.     return(yoono.utils.getExtensionVersion());
  236.   }
  237.  
  238.   this.methods.disableSync = function() {
  239.     YOONO_PREFS.set('nosynchro', true, YNPREFS.PREF_BOOL);
  240.   }
  241.  
  242.   this.methods.runSync = function(params) {
  243.       var observer = params[0];
  244.       // syncMode should be either first-sync or manual-sync
  245.       var syncMode = params[1];
  246.  
  247.       var obsSrvc = Components.classes['@mozilla.org/observer-service;1'].getService(Components.interfaces.nsIObserverService);
  248.       _self.syncObserver = {
  249.         // called when sync is over.
  250.         observe : function(subject, topic, data) {
  251.           try {
  252.               yoono.log.debug('sidebarExternal.runSunc.observe : got topic ' + topic);
  253.               switch(topic) {
  254.                 case "yoono-synchro-useless":
  255.                   // manual-sync was done, and was useless : must reset the nosynchro flag
  256.                   YNPREFS.setBoolPref("nosynchro" , false); // -> no longer launch a connect !
  257.                   // NO BREAK on purpose
  258.                 case "yoono-synchro-end":
  259.                   var obsSrvc = Components.classes['@mozilla.org/observer-service;1'].getService(Components.interfaces.nsIObserverService);
  260.                   obsSrvc.removeObserver(_self.syncObserver,"yoono-synchro-end");
  261.                   obsSrvc.removeObserver(_self.syncObserver,"yoono-synchro-useless");
  262.                   // notify wizard in sidebar
  263.                   observer.notifyEndSync();
  264.                   break;
  265.               }
  266.           } catch(e) { yoono.log.exception(e) }
  267.         }
  268.       }
  269.       obsSrvc.addObserver(_self.syncObserver,"yoono-synchro-end"  , false);
  270.       obsSrvc.addObserver(_self.syncObserver,"yoono-synchro-useless"  , false);
  271.       yoono.server.launch('connect',syncMode);
  272.   };
  273.  
  274.   this.methods.playSound = function(url) {
  275.     var surl = Components.classes["@mozilla.org/network/standard-url;1"].createInstance(Components.interfaces.nsIURL);
  276.     surl.spec = url;
  277.     YOONO_SOUND.play(surl);
  278.   };
  279.  
  280.   this.methods.subscribeToAllBrowserEvt = function(observer) {
  281.     _self._browserObservers.push(observer);
  282.     _self.notifyAlreadyOpenTabActivity(observer);
  283.   };
  284.   this.methods.unsubscribeToAllBrowserEvt = function(observer) {
  285.     _self._browserObservers.splice(_self._browserObservers.indexOf(observer),1);
  286.   };
  287.  
  288.   // Open a page with the user's authentication headers, and optionnal additional headers
  289.   this.methods.openUrlLogin = function(params) {
  290.     var loginPage = "http://api.yoono.com/my-yoono/sign_in.jsp" ;
  291.     params[0] = loginPage + params[0] ;
  292.     var userLoginInfo = _self.methods.getUserCredential();
  293.     if(!userLoginInfo || userLoginInfo.anonymous) return;
  294.     var login = userLoginInfo.login;
  295.     var password = userLoginInfo.password;
  296.     if(!(2 in params)) params[2] = [];
  297.     params[2].push('X-Login: ' + login);
  298.     params[2].push('X-Password: ' + password);
  299.     _self.methods.openUrl(params);
  300.   }
  301.  
  302.   
  303.   this.methods.renameCookiesKey = function(params) {
  304.     var src = params[0];
  305.     var dst = params[1];
  306.     var name = params[2];
  307.     var avatar = params[3];
  308.     var providerId = params[4];
  309.     
  310.     if (typeof CookiesService!="object") return;
  311.     
  312.     CookiesService.renameSession(src,dst);
  313.     if (name || avatar) {
  314.       var network = yoono.main.getYServices().accountsManager.getProviderDisplayName(providerId);
  315.       CookiesService.setSessionInfo(dst, name, avatar, network, providerId);
  316.     }
  317.   }
  318.   
  319.   this.methods.setCookiesInfo = function(params) {
  320.     var sessionId = params[0];
  321.     var name = params[1];
  322.     var avatar = params[2];
  323.     var providerId = params[3];
  324.     var network = yoono.main.getYServices().accountsManager.getProviderDisplayName(providerId);
  325.     
  326.     if (typeof CookiesService!="object") return;
  327.     
  328.     CookiesService.setSessionInfo(sessionId, name, avatar, network, providerId);
  329.   }
  330.   
  331.   this.methods.deleteCookiesInfo = function (params) {
  332.     var sessionId = params[0];
  333.     
  334.     if (typeof CookiesService!="object") return;
  335.     CookiesService.deleteSessionInfo(sessionId);
  336.   }
  337.   
  338.   this.methods.openUrl = function(params) {
  339.     var url = params[0];
  340.     var mode = params[1] || 'new-tab';
  341.     var headerArray = params[2] || [];
  342.     var mandatoryInStandalone = params[3] || false; // mandatory open this url in xulrunner (not in system browser!)
  343.     var accountId = params[4] || -1;
  344.     
  345.     //yoono.main.getYServices().log.backtrace("openUrl : "+url+"\n"+accountId+"\n");
  346.     
  347.     // 1) Retrieve a reference to a <browser> object
  348.     var browser;
  349.     if (_self.methods.isStandalone()) {
  350.       if (!mandatoryInStandalone && YOONO_PREFS.get("open-in-system-browser")) {
  351.         _self.getTopWindow().ynWebPanel.openUrlInSystemBrowser(url);
  352.         return;
  353.       }
  354.       browser = _self.getTopWindow().ynWebPanel.openBrowser(mandatoryInStandalone);
  355.     } else {
  356.       var tab = _self.getTopWindow().gBrowser.addTab("about:blank");
  357.       _self.getTopWindow().gBrowser.selectedTab = tab;
  358.     
  359.       browser = tab.linkedBrowser;
  360.     }
  361.     
  362.     // 2) If we reveice an account argument,
  363.     //    Create and register a new Cookies database
  364.     if (accountId!=-1 && typeof CookiesService=="object") {
  365.       _self.getTopWindow().gAccountSelector.displayInfoBubble();
  366.       CookiesService.attachSessionToBrowser(browser, accountId, goLoadURI);
  367.     } else {
  368.       goLoadURI();
  369.     }
  370.     
  371.     function goLoadURI() {
  372.       
  373.       // Build a valid XPCOM headers structure
  374.       var headers = {};
  375.       for(var i=0;i<headerArray.length; i++) {
  376.         var semiC = headerArray[i].indexOf(':');
  377.         if(-1 == semiC) continue;
  378.         var name = headerArray[i].substr(0 , semiC);
  379.         var value = headerArray[i].substr(semiC + 1);
  380.         headers[name] = value;
  381.       }
  382.       if(!('Referer' in headers)){
  383.         headers['Referer'] = 'http://www.yoono.com';
  384.       }
  385.       var aHeaders = Components.classes["@mozilla.org/network/mime-input-stream;1"].createInstance(Components.interfaces.nsIMIMEInputStream);
  386.       for (var i in headers) {
  387.         aHeaders.addHeader(i, headers[i]);
  388.       }
  389.       
  390.       // Go!!!
  391.       browser.webNavigation.loadURI(url, null, null, null, aHeaders);
  392.       
  393.     }// end of goLoadURI
  394.     
  395.   }
  396.  
  397.  
  398.   this.methods.getMemoMgr = function() {
  399.     var memoMgr = null;
  400.     try {
  401.       // MemoMgr needs some methods published by the add-on
  402.       var methods = new Object();
  403.       methods.subscribeToBrowserEvt = function(subscriber) {
  404.         yoono.reco.subscribeToRequest(subscriber)
  405.       };
  406.       methods.unsubscribeToBrowserEvt = function(unsubscriber) {
  407.         yoono.reco.unsubscribeToRequest(unsubscriber)
  408.       };
  409.       methods.openUrl = _self.methods.openUrl;
  410.       
  411.       methods.deleteKeyValue = function(key) {
  412.         return YOONO_KEYVALUEDB.deleteKeyValue('memomgr.' + key);
  413.       };
  414.       methods.getKeyValue = function(key) {
  415.         return YOONO_KEYVALUEDB.getKeyValue('memomgr.' + key);
  416.       };
  417.       methods.setKeyValue = function(key, value, days) {
  418.         YOONO_KEYVALUEDB.setKeyValue('memomgr.' + key, value, days);
  419.       };
  420.       
  421.       methods.logError = yoono.log.error;
  422.       methods.logWarning = yoono.log.warn;
  423.       methods.logInfo = yoono.log.info;
  424.       methods.logDebug = yoono.log.debug;
  425.       
  426.       methods.getFeedServerUrl = function() {
  427.         return(_self.methods.getPref('feedserver'));
  428.       }
  429.       // if memoManager was already created, it will be returned
  430.       // if user changed, it will be updated to connect to new user account
  431.       memoMgr = yoono.sidebar.getMemoMgr(methods);
  432.     } catch(e) {
  433.       yoono.log.exception(e);
  434.     }
  435.     return(memoMgr);
  436.   }
  437.  
  438.   this.methods.calcUTF8_MD5 = function(aString) {
  439.     
  440.     var converter =
  441.       Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].
  442.         createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
  443.  
  444.     // we use UTF-8 here, you can choose other encodings.
  445.     converter.charset = "UTF-8";
  446.     // result is an out parameter,
  447.     // result.value will contain the array length
  448.     var result = {};
  449.     // data is an array of bytes
  450.     var data = converter.convertToByteArray(aString, result);
  451.     var ch = Components.classes["@mozilla.org/security/hash;1"]
  452.                        .createInstance(Components.interfaces.nsICryptoHash);
  453.     ch.init(ch.MD5);
  454.     ch.update(data, data.length);
  455.     var hash = ch.finish(false);
  456.  
  457.     // return the two-digit hexadecimal code for a byte
  458.     function toHexString(charCode)
  459.     {
  460.       return ("0" + charCode.toString(16)).slice(-2);
  461.     }
  462.  
  463.     // convert the binary hash data to a hex string.
  464.     var s = [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");
  465.     
  466.     return s;
  467.   }
  468.  
  469.   this.methods.setUserId = function(userId) {
  470.     yoono.main.changeUser(userId);
  471.   };
  472.  
  473.   // Returns a pref from prefs in extensions.yoono. branch
  474.   this.methods.getPref = function(prefName) {
  475.     return YOONO_PREFS.get(prefName);
  476.   };
  477.   this.methods.setPref = function(params) {
  478.     var prefName=params[0], prefValue=params[1];
  479.     return YOONO_PREFS.set(prefName, prefValue);
  480.   };
  481.   this.methods.getLogLevel = function(prefName) {
  482.     return(YOONO_PREFS.get('debug.level'))
  483.   };
  484.   
  485.   this.methods.getKeyValueList = function(keyPattern) {
  486.     return YOONO_KEYVALUEDB.getKeyValueList(keyPattern);
  487.   };
  488.   this.methods.deleteKeyValue = function(key) {
  489.     return YOONO_KEYVALUEDB.deleteKeyValue(key);
  490.   };
  491.   this.methods.getKeyValue = function(key) {
  492.     return YOONO_KEYVALUEDB.getKeyValue(key);
  493.   };
  494.   this.methods.setKeyValue = function(params) {
  495.     var key = params[0];
  496.     var value = params[1];
  497.     var days = 0;
  498.     if (2 in params) days = params[2];
  499.     YOONO_KEYVALUEDB.setKeyValue(key, value, days);
  500.   };
  501.  
  502.   this.methods.allowCookiesForHost = function(hostname) {
  503.     var ioService = Components.classes["@mozilla.org/network/io-service;1"]
  504.                                 .getService(Components.interfaces.nsIIOService);
  505.     var uri = ioService.newURI('http://'  + hostname, null, null);
  506.     COOKIE_PERM.setAccess(uri, COOKIE_PERM.ACCESS_ALLOW);
  507.   }
  508.  
  509.   this.methods.getCookiesForHost = function(hostname) {
  510.     var result = [];
  511.     var iter = COOKIE_MAN.enumerator;
  512.     while (iter.hasMoreElements()) {
  513.       var cookie = iter.getNext();
  514.       if (cookie instanceof Components.interfaces.nsICookie) {
  515.         if (cookie.host == hostname) {
  516.           result.push({
  517.             host: cookie.host,
  518.             path: cookie.path,
  519.             name: cookie.name,
  520.             value: cookie.value,
  521.             expires: cookie.expires
  522.           });
  523.         }
  524.       }
  525.     }
  526.     return result;
  527.   }
  528.  
  529.   this.methods.addCookie = function(params) {
  530.     yoono.log.debug("Add cookie: " + params);
  531.     COOKIE_MAN.add(params[0],
  532.                    params[1],
  533.                    params[2],
  534.                    params[3],
  535.                    false,
  536.                    false,
  537.                    false,
  538.                    params[4]);
  539.   }
  540.  
  541.   this.methods.removeCookiesForHost = function(aHost) {
  542.     var toDelete = [];
  543.     var iter = COOKIE_MAN.enumerator;
  544.     while (iter.hasMoreElements()) {
  545.       var cookie = iter.getNext();
  546.       if (cookie instanceof Components.interfaces.nsICookie) {
  547.         if (cookie.host == aHost) {
  548.           toDelete.push(cookie);
  549.         }
  550.       }
  551.     }
  552.     for (i = 0; i < toDelete.length; i++) {
  553.       var cookie = toDelete[i];
  554.       COOKIE_MAN.remove(cookie.host, cookie.name, cookie.path, false);
  555.     }
  556.   }
  557.  
  558.   this.methods.getSelectedText = function() {
  559.     return(_self.getYoonoGlob().getSelectedText());
  560.   }
  561.  
  562.   this.methods.setThin = function(thinWidth) {
  563.     _self.getSidebar().setThin(thinWidth);
  564.   }
  565.  
  566.   // set a stat counter that will be sent every 24 hours
  567.   this.methods.setStat = function(params) {
  568.     var statName = params[0];
  569.     var value = params[1];
  570.     yoono.main.setStat([statName], value);
  571.   }
  572.   // increments a stat counter by a given amount
  573.   this.methods.incStatBy = function(params) {
  574.     var statName = params[0];
  575.     var value = params[1];
  576.     yoono.main.addStat([statName], value);
  577.   }
  578.   // increments a stat counter that will be sent every 24 hours
  579.   this.methods.incStat = function(statName) {
  580.     yoono.main.addStat([statName], 1);
  581.   }
  582.  
  583.   this.methods.setLarge = function(largeWidth) {
  584.     _self.getSidebar().setLarge(largeWidth);
  585.   }
  586.  
  587.   // Open a popup for a Yoodget that is being extracted from the sidebar
  588.   this.methods.popout = function(params) {
  589.     try {
  590.       var owner = params[0];
  591.       var url = params[1];
  592.       var props = params[2];
  593.       var yuid = params[3];
  594.       var instance = params[4];
  595.       var sidebarId = params[5];
  596.       var yoodgetParams = params[6];
  597.  
  598.       var propsStr = '';
  599.       for (var i in props) {
  600.         propsStr += i + '=' + props[i] + ',';
  601.       }
  602.  
  603.       // we need a value different for each call
  604.       var openTime = new Date().getTime() + Math.floor((Math.random() * 100000));
  605.       var popup = _self.getTopWindow().open(url, openTime, propsStr);
  606.       popup.ynSidebar = owner;
  607.       popup.addEventListener('DOMContentLoaded',
  608.               function(e) {
  609.                 try {
  610.                   if(e.explicitOriginalTarget.defaultView==popup){
  611.                     for (var method in _self.methods) {
  612.                       popup.YEXTIF.methods[method] = _self.methods[method];
  613.                     }
  614.                     yoono.main.getYServices().core.initSubDocument(popup,"yoonoPopoutInit",[yoodgetParams]);
  615.                   }
  616.                 } catch(e) {
  617.                   yoono.log.exception(e);
  618.                 }
  619.               },
  620.               true);
  621.       if (props.left && props.top)
  622.         popup.moveTo(props.left, props.top);
  623.       // add it to popouted windows  list (in extension)
  624.       var key = yuid + instance + '-' + sidebarId;
  625.       _self.popouted[key] = popup;
  626.     } catch (e) {
  627.       yoono.log.exception(e);
  628.     }
  629.   }
  630.   // Re-insert a Yoodget in the sidebar
  631.   this.methods.popin = function(params) {
  632.     try {
  633.       var url = params[0];
  634.       var instance = params[1];
  635.       _self.getSidebar().win.ynSidebar.addYoodget({'url': url, 'view' : 'block', 'instance': instance, 'pinnedDown':true});
  636.       _self.getSidebar().win.ynSidebar.setSortable();
  637.     } catch (e) {
  638.       yoono.log.exception(e);
  639.     }
  640.   }
  641.  
  642.   this.methods.checkIfAlreadyPopouted = function(params) {
  643.     var yuid = params[0];
  644.     var instance = params[1];
  645.     var sidebarId = params[2];
  646.     var result = null;
  647.     var key = yuid + instance + '-' + sidebarId;
  648.     if (key in _self.popouted) {
  649.       result = true;
  650.     }
  651.     if (result)
  652.       return(_self.popouted[key]);
  653.     else
  654.       return(null);
  655.   }
  656.   
  657.   
  658.   this.methods.openSidebar = function(windowId) {
  659.     var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  660.                      .getService(Components.interfaces.nsIWindowMediator);
  661.     var enumerator = wm.getEnumerator("navigator:browser");
  662.     while(enumerator.hasMoreElements()) {
  663.       var win = enumerator.getNext();
  664.       var winId = _self.getWindowId(win);
  665.       if (winId==windowId) {
  666.         win.yoonoGlob.sidebar.show();
  667.       }
  668.     }
  669.   }
  670.   
  671.   this.methods.closeSidebar = function() {
  672.     _self.getSidebar().toggle(); // toggle will close it because we can call it only if sidebar is open
  673.   }
  674.  
  675.   // Open a popup to show properties and actions for an element
  676.   // Only one such popup can be opened at a time. If this method is called while one is already opened, close it first
  677.   this.methods.singletonPopup = function(params) {
  678.     try {
  679.       _self.closeSingletonPopup();
  680.       _self.singletonPopup = _self.methods.popup(params);
  681.     } catch(e) {
  682.       yoono.log.exception(e);
  683.     }
  684.     return(_self.singletonPopup);
  685.   }
  686.  
  687.   // Open a popup that is not a popouted yoodget
  688.   this.methods.popup = function(params) {
  689.     try {
  690.       var owner = params[0];
  691.       var url = params[1];
  692.       var name = params[2];
  693.       var props = params[3];
  694.       var extraParams = params[4];
  695.       
  696.       // manual centerscreen ... see bottom
  697.       var centerscreen = props.centerscreen && props.centerscreen!="no";
  698.       delete props.centerscreen;
  699.       
  700.       if (!props.left)
  701.         props.left=_self.getTopWindow().screenX;//.availLeft;
  702.       if (!props.top)
  703.         props.top=_self.getTopWindow().screenY;//.availTop;
  704.       
  705.       var propsStr = '';
  706.       for (var i in props) {
  707.         propsStr += i + '=' + props[i] + ',';
  708.       }
  709.       propsStr = propsStr.replace(/,$/, '');
  710.       
  711.       // we need a different URL each time, otherwise an already opened window will be reloaded before 
  712.       // we set the event lister that calls the init procedure...
  713.       if (-1 == url.indexOf('#')) {
  714.         url += '#' + Math.floor(Math.random() * 100000);
  715.       }
  716.       
  717.       var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].getService(Components.interfaces.nsIWindowWatcher);
  718.       var old=ww.getWindowByName(name,null);
  719.       if (old) {
  720.         old.close();
  721.       }
  722.       
  723.       var popup = _self.getTopWindow().open(url, name, propsStr);
  724.       function onload(e) {
  725.         popup.removeEventListener('DOMContentLoaded',onload,false);
  726.         try {
  727.           if(e.explicitOriginalTarget.defaultView==popup) {
  728.             // for when there is no sidebar
  729.             for (var method in _self.methods) {
  730.               popup.YEXTIF.methods[method] = _self.methods[method];
  731.             }          
  732.             yoono.main.getYServices().core.initSubDocument(popup,"yoonoPopupInit",[owner, extraParams]);
  733.           }
  734.         } catch(e) {
  735.           yoono.log.exception(e);
  736.         }
  737.       }
  738.       popup.addEventListener('DOMContentLoaded', onload, false);
  739.       
  740.       // manual center screen...
  741.       // https://bugzilla.mozilla.org/show_bug.cgi?id=410337
  742.       if (centerscreen) {
  743.         var sm = Components.classes["@mozilla.org/gfx/screenmanager;1"].getService(Components.interfaces.nsIScreenManager);
  744.         var sc = sm.screenForRect(_self.getTopWindow().screenX, _self.getTopWindow().screenY, 10, 10);
  745.         var left={},top={},width={},height={};
  746.         sc.GetAvailRect(left,top,width,height);
  747.         
  748.         popup.moveTo(
  749.           left.value+(width.value-popup.outerWidth)/2,
  750.           top.value+(height.value-popup.outerHeight)/2
  751.           );
  752.         
  753.       }
  754.     } catch(e) {
  755.       yoono.log.exception(e);
  756.     }
  757.     return(popup);
  758.   }
  759.  
  760.   // This will return a array with the bookmarks
  761.   this.methods.getBookmarks = function(params) {
  762.     var target = yoono.bkm.getCurrentTree();
  763.     params = params[0];
  764.     for (var i = 0; i < params.length; i++) {
  765.       target = target.childsList[params[i]];
  766.     }
  767.     
  768.     var result = new Array();
  769.     var type = "bookmark";
  770.     var path = "";
  771.     for (var j in target.childsList) {
  772.       path = '';
  773.       switch(target.childsList[j].type) {
  774.         case "http://home.netscape.com/NC-rdf#BookmarkSeparator" :
  775.           type = "separator";
  776.           break;
  777.  
  778.         case 2:   // FF3
  779.         case "http://home.netscape.com/NC-rdf#Folder" :  // FF2
  780.           if(target.childsList[j].url) type = 'bookmark'  // FF3 : rss bkms are folders, with an url...
  781.           else type = "folder";
  782.           path = target.childsList[j].path.toServer;
  783.           break;
  784.         default:
  785.           type = "bookmark";
  786.       }
  787.       var name = target.childsList[j].name;
  788.       if('NOTITLE-rdf' == target.childsList[j].name.substr(0,11)) name = "";
  789.       if ('PERSONAL_BOOKMARK_FOLDER' == name) {
  790.         var tb = _self.getTopWindow().document.getElementById('PersonalToolbar');
  791.         if (tb) {
  792.           name = tb.getAttribute('toolbarname') || 'Personal toolbar';
  793.         }
  794.       }
  795.       result.push({'title': name, 'url': target.childsList[j].url,
  796.                    'type': type, 'path' : path});
  797.     }
  798.     target = null;
  799.     return result;
  800.   }
  801.  
  802.   // this is called by each yoodget in their init method so that actions can be taken
  803.   // in the FF add-on part
  804.   this.methods.yoodgetInSidebar = function(yuid) {
  805.     switch(yuid) {
  806.       case '{memo@yoono.com}':
  807.         // In each opened window, show the webnote related menu items
  808.         yoono.dialogs.traverseBrowsers(function(aWin) {
  809.           var doc = aWin.document;
  810.           var menuitem = doc.getElementById('yoono-context-menuitem');
  811.           if(menuitem) menuitem.removeAttribute('hidden');
  812.           menuitem = doc.getElementById('yoono-mymemos-menuitem');
  813.           if(menuitem) menuitem.removeAttribute('hidden');
  814.         });
  815.       break;
  816.     }
  817.   }
  818.  
  819.   // reads the yoodgets manifest file and returns its content
  820.   this.methods.getYoodgets = function(params) {
  821.     try {
  822.       var config = params[0];
  823.       // Request the external yoodgets file
  824.       // NO LONGER
  825.       //yoono.main.sendRequest('http://www.yoono.com/yoodgets.xml', 'get', 'async', '', function(req, res) {
  826.         //_self.handleExternalYoodgets(req, res, config)
  827.       //});
  828.       var manifestList = new Array();
  829.       
  830.       var rootDir = YOONO_DIRSERVICE.get("ProfDS", Components.interfaces.nsIFile);
  831.       rootDir.append('extensions');
  832.       rootDir.append(YOONO_ID);
  833.       
  834.       if (!rootDir.exists()) {
  835.         // Xulrunner 
  836.         // set rootDir to path where extension is located
  837.         rootDir = null;
  838.         var extDirs = YOONO_DIRSERVICE.get("XREExtDL", Components.interfaces.nsISimpleEnumerator);
  839.         while(extDirs.hasMoreElements()) {
  840.           var dir = extDirs.getNext().QueryInterface(Components.interfaces.nsIFile);
  841.           dir.append('chrome');
  842.           dir.append('m');
  843.           dir.append('yoono.com');
  844.           dir.append('sidebar');
  845.           if (dir.exists()) {
  846.             rootDir = dir;
  847.             break;
  848.           }
  849.         }
  850.         if (!rootDir) {
  851.           var content = _self.methods.readFile("yoodgets.xml");
  852.           if (!content)
  853.             return yoono.log.error("Unable to fetch yoodgets list");
  854.           config.setYoodget(content);
  855.         }
  856.         //rootDir = YOONO_DIRSERVICE.get("resource:app", Components.interfaces.nsIFile);
  857.         //rootDir.append('extensions');
  858.         //rootDir.append(YOONO_ID);
  859.         //rootDir.append('chrome');
  860.         //rootDir.append('m');
  861.         //rootDir.append('yoono.com');
  862.         //rootDir.append('sidebar');
  863.         var dirEntries = rootDir.directoryEntries;
  864.         while (dirEntries.hasMoreElements()) {
  865.           var file = dirEntries.getNext().QueryInterface(Components.interfaces.nsIFile);
  866.           if (!file || !file.isDirectory()) continue;
  867.           file.append('yoodget.manifest');
  868.           if (file.exists()) {
  869.             manifestList.push(file);
  870.           }
  871.         }
  872.       }
  873.       else if (!rootDir.isDirectory()) {
  874.         // if dev (extension entry is a file, not a directory)
  875.         // read file to get path of dev extension
  876.         var istream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
  877.         istream.init(rootDir, 0x01, 0444, 0);
  878.         istream.QueryInterface(Components.interfaces.nsILineInputStream);
  879.         var line = {};
  880.         istream.readLine(line);
  881.         istream.close();
  882.         rootDir = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
  883.         // set rootDir to path where extension is located
  884.         rootDir.initWithPath(line.value);
  885.         rootDir.append('chrome');
  886.         rootDir.append('m');
  887.         rootDir.append('yoono.com');
  888.         rootDir.append('sidebar');
  889.         var dirEntries = rootDir.directoryEntries;
  890.         while (dirEntries.hasMoreElements()) {
  891.           var file = dirEntries.getNext().QueryInterface(Components.interfaces.nsIFile);
  892.           if (!file || !file.isDirectory()) continue;
  893.           file.append('yoodget.manifest');
  894.           if (file.exists()) {
  895.             manifestList.push(file);
  896.           }
  897.         }
  898.       } else {
  899.         // when xpi installed, use the local yoodgets.xml file that list all yoodgets
  900.         // this file was created by the build script
  901.         yoono.main.sendRequest('chrome://yoonosb/content/yoodgets.xml', 'get', 'async', '', function(req, res) {
  902.           _self.handleExternalYoodgets(req, res, config)
  903.         });
  904.         return;
  905.       }
  906.       for(var i=0 ; i < manifestList.length; i++) {
  907.         var file = manifestList[i];
  908.         var istream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
  909.         istream.init(file, 0x01, 0444, 0);
  910.         istream.QueryInterface(Components.interfaces.nsILineInputStream);
  911.         var converter = Components.classes["@mozilla.org/intl/converter-input-stream;1"].createInstance(Components.interfaces.nsIConverterInputStream);
  912.         converter.init(istream, 'UTF-8', 1024, '-');
  913.         var line = {};
  914.         var hasmorelines;
  915.         var content = '';
  916.         while (converter.readString(4096, line)) {
  917.           content += line.value;
  918.         }
  919.         istream.close();
  920.         config.setYoodget(content);
  921.       }
  922.     } catch(e) {
  923.       yoono.log.exception(e);
  924.     }
  925.   }
  926.  
  927.   // Read synchronously a file from its url
  928.   // (Real synchronous ... not a FF3's xmlhttprequest fake!)
  929.   this.methods.readFile = function (param) {
  930.     var str = '';
  931.     try {
  932.       url = "chrome://yoonosb/content/" + param.replace(/\.\./g, '');
  933.       var ioService=Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
  934.       var scriptableStream=Components.classes["@mozilla.org/scriptableinputstream;1"]
  935.         .getService(Components.interfaces.nsIScriptableInputStream);
  936.       var channel=ioService.newChannel(url,'UTF-8',null);
  937.       // TODO : solve UTF8 handling...
  938.       var input=channel.open();
  939.       scriptableStream.init(input);
  940.        str=scriptableStream.read(input.available());
  941.        scriptableStream.close();
  942.       input.close();
  943.     } catch(e) {
  944.       yoono.log.exception(e);
  945.     }
  946.     return str;
  947.   }
  948.  
  949. } // end of setMethods()
  950.  
  951. YoonoExternalInterfaces.prototype.getTopWindow = function () {
  952.   return WMED.getMostRecentWindow("navigator:browser");
  953. }
  954.  
  955. YoonoExternalInterfaces.prototype.setSbIframe = function(iframe) {
  956.   this.sbIframe = iframe;
  957. }
  958.  
  959. YoonoExternalInterfaces.prototype.closeSingletonPopup = function() {
  960.   this.closePopup(this.singletonPopup);
  961. }
  962.  
  963. YoonoExternalInterfaces.prototype.closePopup = function(popup) {
  964.   try {
  965.     popup.close();
  966.   } catch(e) {
  967.   }
  968. }
  969.  
  970. // When closing a FF window, close associated popups
  971. YoonoExternalInterfaces.prototype.goodbye = function() {
  972.   this.closeSingletonPopup();
  973.   for (var i in this.popouted) {
  974.     this.closePopup(this.popouted[i]);
  975.   }
  976. }
  977.  
  978. YoonoExternalInterfaces.prototype.handleExternalYoodgets = function(req, res, config) {
  979.   var text = req.responseText;
  980.   config.setYoodget(text);
  981. }
  982.  
  983. // TODO : NEEDS TESTING.  and using.
  984. YoonoExternalInterfaces.prototype.findReloadTab = function(url) {
  985.   var result = false;
  986.   var tabbrowser = this.getTopWindow().getBrowser();
  987.   var panels = tabbrowser.mPanelContainer.childNodes;
  988.   var panel = null;
  989.   var panelUrl = null;
  990.   var docContainer = null;
  991.   for (var i = 0; i < panels.length; i++) {
  992.     panel = panels[i];
  993.     docContainer = panel.firstChild;
  994.     while (!docContainer.contentDocument && docContainer.nextSibling) {
  995.       docContainer = docContainer.nextSibling;
  996.     }
  997.     if (docContainer.contentDocument) {
  998.       panelUrl = docContainer.contentDocument.URL;
  999.       if (panelUrl == url) {
  1000.         result = true;
  1001.       }
  1002.     }
  1003.   }
  1004.   return(result);
  1005. }
  1006.  
  1007. YoonoExternalInterfaces.prototype._browserObservers = [];
  1008.  
  1009. YoonoExternalInterfaces.prototype.isPrivateModeEnabled = function () {
  1010.   var pbs = false;
  1011.   try {
  1012.     pbs = Components.classes["@mozilla.org/privatebrowsing;1"].getService(Components.interfaces.nsIPrivateBrowsingService);
  1013.   } catch(e) {}
  1014.   return pbs?pbs.privateBrowsingEnabled:false;
  1015. }
  1016.  
  1017. // Called from yoonoOverlay.js in each firefox window
  1018. // Call all observers registered with YEXTIF.subscribeToAllBrowserEvent
  1019. YoonoExternalInterfaces.prototype.notifyTabActivity = function (windowId, doc, url, state) {
  1020.   if (state=="loaded")
  1021.     doc.loaded=true;
  1022.   if (this.isPrivateModeEnabled()) {
  1023.     url="about:privatebrowsing";
  1024.     //doc={};
  1025.   }
  1026.   for(var i=0; i<this._browserObservers.length; i++) {
  1027.     try {
  1028.       this._browserObservers[i].notify(windowId, doc, url, state);
  1029.     } catch(e) {
  1030.       yoono.log.exception(e);
  1031.     }
  1032.   }
  1033. }
  1034. YoonoExternalInterfaces.prototype.notifyAlreadyOpenTabActivity = function (observer) {
  1035.   try {
  1036.     if (this.isPrivateModeEnabled()) {
  1037.       url="about:privatebrowsing";
  1038.       //doc={};
  1039.     }
  1040.     var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  1041.                      .getService(Components.interfaces.nsIWindowMediator);
  1042.     var enumerator = wm.getEnumerator("navigator:browser");
  1043.     while(enumerator.hasMoreElements()) {
  1044.       var win = enumerator.getNext();
  1045.       var winId = this.getWindowId(win);
  1046.       var doc = win.document.getElementById("content").contentDocument;
  1047.       if (doc.loaded || doc.location.href=="about:blank") { // about:blank does'nt generate any notifyTabActivity ... so his doc.loaded never became true
  1048.         observer.notify(winId, doc, doc.location.href, "loaded");
  1049.       }
  1050.     }
  1051.   } catch(e) {
  1052.     yoono.log.exception(e);
  1053.   }
  1054. }
  1055.  
  1056.  
  1057. YoonoExternalInterfaces.prototype.currentWindowId = 1;
  1058. YoonoExternalInterfaces.prototype.getWindowId = function (win) {
  1059.   if (!win.windowId)
  1060.     win.windowId = "window-"+(this.currentWindowId++)+"-"+new Date().getTime();
  1061.   return win.windowId;
  1062. }
  1063.  
  1064.  
  1065.  
  1066. var YOONO_YEXTIF = new YoonoExternalInterfaces();
  1067.